package com.yehui.jdk.concurrent;

import com.yehui.jdk.reflect.ReflectFun;

import java.util.Collections;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author 业徽
 * @date 2021/3/16
 */
public class ThreadPoolExecutorFun {

    /**
     * 打印 threadPool 里的常量
     */
    public void printThreadPoolExecutorConstant() throws NoSuchFieldException, IllegalAccessException {

        printSingleThreadPoolExecutorConstant("COUNT_BITS");
        printSingleThreadPoolExecutorConstant("CAPACITY");
        printSingleThreadPoolExecutorConstant("RUNNING");
        printSingleThreadPoolExecutorConstant("SHUTDOWN");
        printSingleThreadPoolExecutorConstant("STOP");
        printSingleThreadPoolExecutorConstant("TIDYING");
        printSingleThreadPoolExecutorConstant("TERMINATED");
    }

    public void shutdown() throws InterruptedException {
        final ExecutorService executorService = new ThreadPoolExecutor(1, 1,
                0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<Runnable>());
        for (int i = 0; i < 20; i++) {
            int finalI = i;
            executorService.execute(() -> {
                System.out.println("i: " + finalI);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }
        executorService.shutdown();
//        executorService.awaitTermination(Integer.MAX_VALUE, TimeUnit.SECONDS);
//        while (true) {
//            if (executorService.isTerminated()) {
//                System.out.println("executor is terminated");
//                System.out.println("queue size is " + ((ThreadPoolExecutor) executorService).getQueue().size());
//                break;
//            }
//            System.out.println("executor is  not terminated");
//            System.out.println("queue size is " + ((ThreadPoolExecutor) executorService).getQueue().size());
//        }
    }

    public void shutdownNow() throws InterruptedException {
        final ExecutorService executorService = new ThreadPoolExecutor(1, 1,
                0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<Runnable>());
        for (int i = 0; i < 20; i++) {
            int finalI = i;
            executorService.execute(() -> {
                System.out.println("i: " + finalI);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }
        executorService.shutdownNow();
        executorService.awaitTermination(Integer.MAX_VALUE, TimeUnit.SECONDS);
        while (true) {
            if (executorService.isTerminated()) {
                System.out.println("executor is terminated");
                System.out.println("queue size is " + ((ThreadPoolExecutor) executorService).getQueue().size());
                break;
            }
            System.out.println("executor is  not terminated");
            System.out.println("queue size is " + ((ThreadPoolExecutor) executorService).getQueue().size());
        }
    }

    private void printSingleThreadPoolExecutorConstant(String name) throws NoSuchFieldException,
            IllegalAccessException {
        final Object value = ReflectFun.getStaticField(ThreadPoolExecutor.class, name);
        String binaryString = Integer.toBinaryString((Integer) value);
        if (binaryString.length() < Integer.SIZE) {

            final String fillZero = String.join("", Collections.nCopies(Integer.SIZE - binaryString.length(), "0"));
            binaryString = fillZero + binaryString;
        }
        System.out.println(name + ": " + value + ", bit: " + binaryString);
    }

    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, InterruptedException {
        final ThreadPoolExecutorFun threadPoolExecutorFun = new ThreadPoolExecutorFun();
        threadPoolExecutorFun.shutdown();
    }

}
